#!/usr/bin/env python
# @Author  : Bright (brt2@qq.com)
# @Create  : 2023-06-12
# @Update  : 2023-11-13 / 0.1.1

import os.path
import json
from abc import ABC, abstractmethod

class RebasePath:
    """ 类似构建了一个目录的软连接 """
    def __init__(self, link_to=None, curfile=None, target_dir=None):
        """
        Usage:
            1. rpath = RebasePath(link_to='../xxx/yyy/')
               or:
               rpath = RebasePath(curfile=__file__ or os.path.abspath("."),
                                  target_dir='/home/xxx/yyy/')
            2. rpath('ttt/xxx')
        """
        if target_dir:
            self._from = target_dir
        elif link_to:
            self._from = link_to
        else:
            curdir_ = curfile if os.path.isdir(curfile) else os.path.dirname(curfile)
            self._from = os.path.relpath(target_dir, curdir_)

    def __call__(self, rpath_to_target_dir):
        """ return a ture-path of input """
        abspath_target = os.path.join(self._from, rpath_to_target_dir)
        # logger.debug(f">>> {abspath_target}")
        return abspath_target

class ConfigLoader(ABC):
    def __init__(self, relpath, curfile=None):
        """
        Usage:
            rpath = RebasePath(relptah="./config.json",
                               curfile=__file__ or os.path.abspath("."))
            2. rpath('ttt/xxx')
        """
        if os.path.isdir(curfile):
            curdir_ = curfile
        else:
            if os.path.islink(curfile):
                curfile = os.path.realpath(curfile)
            curdir_ = os.path.dirname(curfile)

        if os.path.islink(curdir_):
            curdir_ = os.path.realpath(curdir_)
        self._from = curdir_
        self.path_file = os.path.join(self._from, relpath)

    @abstractmethod
    def _load(self):
        pass

    def load(self, default_value=None, template_file=""):
        import shutil

        if not os.path.exists(self.path_file):
            if default_value is None:
                assert template_file, f"[!] 未查询到文件【{self.path_file}】\n请二选一配置`load()`可选参数: [default_value] or [template_file]"
                shutil.copy(os.path.join(self._from, template_file), self.path_file)
            else:
                self.dump(default_value)
                return default_value
        return self._load()

    @abstractmethod
    def dump(self, data):
        pass

class JsonConfigLoader(ConfigLoader):
    def _load(self):
        with open(self.path_file, "r") as fp:
            return json.load(fp)

    def dump(self, data):
        with open(self.path_file, "w") as fp:
            json.dump(data, fp)
